#include "mediacenter.h"

using namespace std;
namespace sct
{
#define checkerror(rtperr) if(rtperr < 0) SCT_LOGE("%s", RTPGetErrorString(rtperr).c_str())

static const char* gLabelConf = "conf";
static const char* gXMLVersion = "1.0";
static const char* gMethodGet = "GET";
static const char* gMethodPost = "POST";

/**
* Context we keep for an upload.
*/
class CUploadContext
{
public:
	uint8_t * data;
	uint32_t len;
	uint32_t max;
};

const char* adjUrl(const char * url, const char * label)
{
	if('\0' == *url)
	{
		url += 0;
	}
	else if(0 == strncmp(url, label, strlen(label)))
	{
		url += strlen(label);
	}
	else
	{
		return NULL;
	}
	if('/' == *url) url++;
	return url;
}

xmlXPathObjectPtr
getnodeset (xmlDocPtr doc, xmlChar *xpath){
	xmlXPathContextPtr context;
	xmlXPathObjectPtr result;
	context = xmlXPathNewContext(doc);
	if (context == NULL) {
		printf("Error in xmlXPathNewContext\n");
		return NULL;
	}
	result = xmlXPathEvalExpression(xpath, context);
	xmlXPathFreeContext(context);
	if (result == NULL) {
		printf("Error in xmlXPathEvalExpression\n");
		return NULL;
	}
	if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
		xmlXPathFreeObject(result);
		printf("No result\n");
		return NULL;
	}
	return result;
}


CMediaCenter::CMediaCenter(const char* conf):
		mState(Initing),
		mRecvThd(NULL),
		mRtspServer(NULL),
		mHttpServ(NULL),
		mMutex(NULL),
		mHashItems(NULL),
		mConfFilePath(conf),
		mTimerBootup(-1),
		mTimerPeriod(-1)
{
	xmlDocPtr doc = xmlParseFile(mConfFilePath.c_str());
	if(NULL == doc)
	{
		SCT_LOGD("Can't load conf file. Exit!");
		exit(-1);
	}

    xmlXPathObjectPtr result;
    xmlNodeSetPtr nodeset;
    int i;
    xmlChar *value;

    ///get ip
    result = getnodeset (doc, (xmlChar*)"/conf/init/ip");
    if(result)
    {
        nodeset = result->nodesetval;
        for (i=0; i < nodeset->nodeNr; i++) {
            value = xmlNodeGetContent(nodeset->nodeTab[i]);

            mMainIp = (char*)value;

            xmlFree(value);
        }

        xmlXPathFreeObject (result);
    }

    ///get http port
    result = getnodeset (doc, (xmlChar*)"/conf/init/httpport");
    if(result)
    {
        nodeset = result->nodesetval;
        for (i=0; i < nodeset->nodeNr; i++) {
            value = xmlNodeGetContent(nodeset->nodeTab[i]);

            mHttpPort = atoi((char*)value);

            xmlFree(value);
        }

        xmlXPathFreeObject (result);
    }

    ///get rtp port
    result = getnodeset (doc, (xmlChar*)"/conf/init/rtpport");
    if(result)
    {
        nodeset = result->nodesetval;
        for (i=0; i < nodeset->nodeNr; i++) {
            value = xmlNodeGetContent(nodeset->nodeTab[i]);

            mRtpPort = atoi((char*)value);

            xmlFree(value);
        }

        xmlXPathFreeObject (result);
    }

    result = getnodeset (doc, (xmlChar*)"/conf/init/rtspport");
    if(result)
    {
        nodeset = result->nodesetval;
        for (i=0; i < nodeset->nodeNr; i++) {
            value = xmlNodeGetContent(nodeset->nodeTab[i]);

            mRtspPort = atoi((char*)value);

            xmlFree(value);
        }

        xmlXPathFreeObject (result);
    }

    ///get file storage path
    result = getnodeset (doc, (xmlChar*)"/conf/init/filestoragepath");
    if(result)
    {
        nodeset = result->nodesetval;
        for (i=0; i < nodeset->nodeNr; i++) {
            value = xmlNodeGetContent(nodeset->nodeTab[i]);

            mFileStoragePath = (char*)value;

            xmlFree(value);
        }

        xmlXPathFreeObject (result);
    }

    result = getnodeset (doc, (xmlChar*)"/conf/init/timeout");
    if(result)
    {
        nodeset = result->nodesetval;
        for (i=0; i < nodeset->nodeNr; i++) {
            value = xmlNodeGetContent(nodeset->nodeTab[i]);

            mTimeoutValue = atoi((char*)value);

            xmlFree(value);
        }

        xmlXPathFreeObject (result);
    }


    xmlFreeDoc(doc);

	mMutex = new CMutex;
	mHashItems = new CHash;

	mHttpServ = MHD_start_daemon (// MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | MHD_USE_POLL,
			MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
			// MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG | MHD_USE_POLL,
			// MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
			mHttpPort,
			NULL, NULL, &accessHandlerCallback,this,
			MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120,
			MHD_OPTION_END);

	///create server
	mRtspServer = CRTSPServerInterface::create("rtspserver", mRtspPort);

	for(int i = 0; i<RtspServerMediaSessionSize; i++)
	{
		CRTSPSessionInfo * item = new CRTSPSessionInfo;

		item->media_session = mRtspServer->createServerMediaSession(toString("/live-%d", i).c_str());
		CRTSPServerInterface::CStreamInfo info;
		info.type = CRTSPServerInterface::TS;
		item->media_subsession = mRtspServer->createServerMediaSubsession(item->media_session, info);

		item->in_use = false;

		mServerSessions[i] = item;
	}
	mRtspServer->init();

	SCT_LOGD("rtsp-0 url:%s", mRtspServer->getUrl(mServerSessions[0]->media_session));

	RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;

	sessparams.SetOwnTimestampUnit(1.0/90000);

	sessparams.SetAcceptOwnPackets(false);
	transparams.SetPortbase(mRtpPort);

	mSess = new RTPSession;
	int status = mSess->Create(sessparams, &transparams);
	checkerror( status );

	mRecvThd = new CThread("rtp_rcv");
	mRecvThd->addCallback(this);
	mRecvThd->start();

	mTimerBootup = addTimer(3000, TT_OneShot);
}

void CMediaCenter::onTimerTimeout(const int id)
{
	SCT_LOGD("timer:%d", id);

	if(id == mTimerBootup)
	{
		mTimerPeriod = addTimer(1000, TT_Periodic);
	}
	else if(id == mTimerPeriod)
	{
//		static int c = 0;
//		c++;
//		if(3 == c)
//		{
//			delTimer(mTimerPeriod);
//		}

		updateActiveItems();
	}
}

void CMediaCenter::updateActiveItems()
{
	CAutoLock locker(mMutex);

	double cur = currentTime();
	std::list<CActiveItem*>::iterator it, it_d;
	for(it = mActiveItems.begin(); it != mActiveItems.end(); )
	{
		CActiveItem * item = *it;

		if(cur - item->last_update_time > mTimeoutValue)
		{
			///lost connection from device
			if(item->rtsp_info)
			{
				item->rtsp_info->in_use = false;
			}
			item->rtsp_info = NULL;

			it_d = it;
			it++;

			SCT_LOGD("del storage point:%d", item->key);
			mActiveItems.erase(it_d);
			mHashItems->del(item->key);
			SCT_DELETE(item);
			continue;
		}
		it++;
	}

	for(it = mActiveItems.begin(); it != mActiveItems.end(); )
	{
		CActiveItem * item = *it;

		if(item->rtsp_info && (cur - item->rtsp_info->last_update_time > mTimeoutValue) )
		{
			///lost connection to client
			item->rtsp_info->in_use = false;

			item->rtsp_info = NULL;

			SCT_LOGD("del streamforward point:%d", item->key);
		}
		it++;
	}
}
int CMediaCenter::main(CThread * caller)
{
	if(caller == mRecvThd)
	{
		recvloop();
	}
	return 0;
}

void CMediaCenter::recvloop()
{
	mState = Running;

	while(Running == mState)
	{
//		static std::ofstream fout("recv.ts");

		mSess->BeginDataAccess();

		int nPackets = 0;
		if(mSess->GotoFirstSourceWithData())
		{
			do
			{
				RTPPacket * pack;

				while( (pack = mSess->GetNextPacket()) != NULL)
				{
					nPackets++;

//					fout.write((char*)pack->GetPayloadData(), pack->GetPayloadLength());
//					mRtspServer->putMediaData( mServerSessions[0]->media_subsession,
//							pack->GetPayloadData(), pack->GetPayloadLength(), currentTime()*1000000);
					uint32_t id;
					memcpy(&id, pack->GetExtensionData(), 4);
					id = ntohl(id);
					mMutex->lock();
					CActiveItem* item = (CActiveItem*)mHashItems->find(id);

					if(item)
					{
						///storage
						if(!item->file.is_open())
						{
							item->file.open(
									std::string(mFileStoragePath + "/"
											+ item->machine + "_"
											+ item->stream_major + "_"
											+ item->stream_minor + ".ts").c_str());
						}

						if(item->file.is_open())
						{
							item->file.write((char*)pack->GetPayloadData(), pack->GetPayloadLength());
						}

						///stream
						if(item && item->rtsp_info)
						{
							mRtspServer->putMediaData( item->rtsp_info->media_subsession,
									pack->GetPayloadData(), pack->GetPayloadLength(), currentTime()*1000000);
						}
					}
					mMutex->unlock();

					mSess->DeletePacket(pack);
				}
			}while(mSess->GotoNextSourceWithData());
		}
		mSess->EndDataAccess();

		SCT_LOGD("got %d packets", nPackets);
		RTPTime::Wait(RTPTime(1, 0));
	}
}

CMediaCenter::~CMediaCenter()
{
	delTimer(mTimerPeriod);

	MHD_stop_daemon(mHttpServ);

	mState = Terminated;
	SCT_DELETE(mRecvThd);

	mSess->BYEDestroy(RTPTime(10, 0), 0, 0);
	SCT_DELETE(mSess);

	for(int i = 0; i<RtspServerMediaSessionSize; i++)
	{
		CRTSPSessionInfo * item = mServerSessions[i];

		SCT_DELETE(item);
	}

	SCT_DELETE(mRtspServer);

	SCT_DELETE(mMutex);
	SCT_DELETE(mHashItems);

	while(!mActiveItems.empty())
	{
		CActiveItem* item = mActiveItems.front();
		mActiveItems.pop_front();

		SCT_DELETE(item);
	}
}

uint32_t CMediaCenter::createStoragePoint(const char * mac, const char * major, const char * minor)
{
	uint32_t ret = 0;

	mMutex->lock();
	///check if exist
	std::list<CActiveItem*>::iterator it;
	for(it = mActiveItems.begin(); it != mActiveItems.end(); it++)
	{
		CActiveItem* item = *it;

		if(item->machine == mac &&
				item->stream_major == major &&
				item->stream_minor == minor)
		{
			mMutex->unlock();
			return item->key;
		}
	}

	///new it
	CActiveItem* item = new CActiveItem;
	item->machine = mac;
	item->stream_major = major;
	item->stream_minor = minor;

	item->last_update_time = currentTime();

	int v = mHashItems->add(item);
	if(-1 == v)
	{
		mMutex->unlock();
		SCT_DELETE(item);

		throw -1;
	}
	item->key = v;
	item->rtsp_info = NULL;
	mActiveItems.push_back(item);

	ret = item->key;
	mMutex->unlock();
	return ret;
}

CMediaCenter::CRTSPSessionInfo* CMediaCenter::findFreeRtspSession()
{
	///assume lock it
	CMediaCenter::CRTSPSessionInfo* ret = NULL;

	for(int i = 0; i<RtspServerMediaSessionSize; i++)
	{
		if(!mServerSessions[i]->in_use)
		{
			return mServerSessions[i];
		}
	}

	return ret;
}

uint32_t CMediaCenter::createStreamforwardPoint(const char * mac, const char* major)
{
	uint32_t ret = 0;
	mMutex->lock();

	std::list<CActiveItem*>::iterator it;
	for(it = mActiveItems.begin(); it != mActiveItems.end(); it++)
	{
		CActiveItem* item = *it;

		if(item->machine == mac &&
				item->stream_major == major)
		{
			if(NULL == item->rtsp_info)
			{
				CRTSPSessionInfo * info = findFreeRtspSession();
				if(NULL == info)
				{
					///too many live stream
					mMutex->unlock();

					throw -1;
				}

				item->rtsp_info = info;
				item->rtsp_info->last_update_time = currentTime();
				item->rtsp_info->in_use = true;
			}

			mMutex->unlock();
			return item->key;
		}
	}

	mMutex->unlock();

	///no match item throw
	throw -2;

	return ret;
}

const char* CMediaCenter::getStreamUrlById(const uint32_t id)
{
	const char* ret = "";

	CAutoLock locker(mMutex);
	std::list<CActiveItem*>::iterator it;
	for(it = mActiveItems.begin(); it!= mActiveItems.end(); it++)
	{
		CActiveItem * item = *it;
		if(item->key == id)
		{
			return mRtspServer->getUrl(item->rtsp_info->media_session);
		}
	}

	return ret;
}
int CMediaCenter::onHttpGetMethon(const char * url, xmlNodePtr node)
{
	SCT_LOGD("url:%s", url);
	int ret = -1;

	std::string str = url;
	int len;
	const char* u0;

	u0 = "/api/mediacenter/filestorages/streamid/";
	len = strlen(u0);
	if(0 == str.compare(0, len, u0))
	{
		str = url + len;

		size_t loc = str.find('/');
		if(string::npos != loc)
		{
			std::string sid = str.substr(0, loc);
			uint32_t id = atoi(sid.c_str());
			SCT_LOGD("get stream id:%d", id);

			str = str.c_str() + loc;
			if(str == "/addr")
			{
				///gen addr info
				xmlNodePtr n0, n1;

				n0 = xmlNewNode(NULL, BAD_CAST "api");
				xmlAddChild(node, n0);

				n1 = xmlNewNode(NULL, BAD_CAST "mediacenter");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "filestorages");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "stream");
				xmlNewProp(n1, BAD_CAST "id", BAD_CAST toString("%d", id).c_str());
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "addr");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "ip");
				xmlNodeSetContent(n1, BAD_CAST mMainIp.c_str());
				xmlAddChild(n0, n1);

				n1 = xmlNewNode(NULL, BAD_CAST "port");
				xmlNodeSetContent(n1, BAD_CAST toString("%d", mRtpPort).c_str());
				xmlAddChild(n0, n1);

				ret = 0;
			}
			else if("/status" == str)
			{
				CAutoLock locker(mMutex);
				///check if active
				CActiveItem * item = (CActiveItem*)mHashItems->find(id);
				if(NULL == item)
				{
					return -1;
				}

				item->last_update_time = currentTime();

				xmlNodePtr n0, n1;

				n0 = xmlNewNode(NULL, BAD_CAST "api");
				xmlAddChild(node, n0);

				n1 = xmlNewNode(NULL, BAD_CAST "mediacenter");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "filestorages");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "stream");
				xmlNewProp(n1, BAD_CAST "id", BAD_CAST toString("%d", id).c_str());
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "status");
				xmlNodeSetContent(n1, BAD_CAST "running");
				xmlAddChild(n0, n1);

				ret = 0;
			}
		}

		return ret;
	}


	u0 = "/api/mediacenter/streamforwards/streamid/";
	len = strlen(u0);
	if(0 == str.compare(0, len, u0))
	{
		str = url + len;

		size_t loc = str.find('/');
		if(string::npos != loc)
		{
			std::string sid = str.substr(0, loc);
			uint32_t id = atoi(sid.c_str());
			SCT_LOGD("get stream id:%d", id);

			str = str.c_str() + loc;
			if(str == "/url")
			{
				///gen addr info
				xmlNodePtr n0, n1;

				n0 = xmlNewNode(NULL, BAD_CAST "api");
				xmlAddChild(node, n0);

				n1 = xmlNewNode(NULL, BAD_CAST "mediacenter");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "streamforwards");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "stream");
				xmlNewProp(n1, BAD_CAST "id", BAD_CAST toString("%d", id).c_str());
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "url");
				xmlNodeSetContent(n1, BAD_CAST getStreamUrlById(id));
				xmlAddChild(n0, n1);

				ret = 0;
			}
			else if("/status" == str)
			{
				CAutoLock locker(mMutex);
				///check if active
				CActiveItem * item = (CActiveItem*)mHashItems->find(id);
				if(NULL == item)
				{
					return -1;
				}

				if(NULL == item->rtsp_info)
				{
					return -2;
				}

				item->rtsp_info->last_update_time = currentTime();

				xmlNodePtr n0, n1;

				n0 = xmlNewNode(NULL, BAD_CAST "api");
				xmlAddChild(node, n0);

				n1 = xmlNewNode(NULL, BAD_CAST "mediacenter");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "streamforwards");
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "stream");
				xmlNewProp(n1, BAD_CAST "id", BAD_CAST toString("%d", id).c_str());
				xmlAddChild(n0, n1);

				n0 = n1;
				n1 = xmlNewNode(NULL, BAD_CAST "status");
				xmlNodeSetContent(n1, BAD_CAST "running");
				xmlAddChild(n0, n1);

				ret = 0;
			}
		}

		return ret;
	}

	return ret;
}

int CMediaCenter::onHttpPostMethon(const char * url, xmlDocPtr doc)
{
	SCT_LOGD("url:%s", url);
	int ret = -1;

	std::string str = url;
	int len;
	const char* u0;

	u0 = "/api/mediacenter/filestorages";
	len = strlen(u0);
	if(0 == str.compare(0, len, u0))
	{
		xmlXPathObjectPtr result;
		xmlNodeSetPtr nodeset;
		int i;
		xmlChar *kmachine, *kmajor, *kminor;
		result = getnodeset (doc, (xmlChar*)"/conf/api/mediacenter/filestorages/filestorage");
		if(result)
		{
			nodeset = result->nodesetval;
			for (i=0; i < nodeset->nodeNr; i++) {
				kmachine = xmlGetProp(nodeset->nodeTab[i], BAD_CAST "machine");
				SCT_LOGD("machine:%s", kmachine);

				kmajor = xmlGetProp(nodeset->nodeTab[i], BAD_CAST "streammajor");
				SCT_LOGD("streammajor:%s", kmajor);

				kminor = xmlGetProp(nodeset->nodeTab[i], BAD_CAST "streamminor");
				SCT_LOGD("streamminor:%s", kminor);

				try
				{
					uint32_t key = createStoragePoint(
							(char*)kmachine,
							(char*)kmajor,
							(char*)kminor);

					char buf[80];
					sprintf(buf, "%u", key);

					xmlNodeSetContent(nodeset->nodeTab[i], BAD_CAST buf);
					ret = 0;
				}
				catch(int err)
				{
					ret = -1;
				}

				xmlFree(kmachine);
				xmlFree(kmajor);
				xmlFree(kminor);
			}
			xmlXPathFreeObject (result);

			return ret;
		}

		return ret;
	}

	u0 = "/api/mediacenter/streamforwards";
	len = strlen(u0);
	if(0 == str.compare(0, len, u0))
	{
		xmlXPathObjectPtr result;
		xmlNodeSetPtr nodeset;
		int i;
		xmlChar *kmachine, *kmajor;
		result = getnodeset (doc, (xmlChar*)"/conf/api/mediacenter/streamforwards/streamforward");
		if(result)
		{
			nodeset = result->nodesetval;
			for (i=0; i < nodeset->nodeNr; i++) {
				kmachine = xmlGetProp(nodeset->nodeTab[i], BAD_CAST "machine");
				SCT_LOGD("machine:%s", kmachine);

				kmajor = xmlGetProp(nodeset->nodeTab[i], BAD_CAST "streammajor");
				SCT_LOGD("streammajor:%s", kmajor);

				try
				{
					uint32_t key = createStreamforwardPoint(
							(char*)kmachine,
							(char*)kmajor);

					char buf[80];
					sprintf(buf, "%u", key);

					xmlNodeSetContent(nodeset->nodeTab[i], BAD_CAST buf);

					ret = 0;
				}
				catch(int err)
				{
					ret = -1;
				}
				xmlFree(kmachine);
				xmlFree(kmajor);
			}
			xmlXPathFreeObject (result);

			return ret;
		}

		return ret;
	}

	return ret;
}

int
CMediaCenter::accessHandlerCallback (void *cls,
	struct MHD_Connection *connection,
	const char *url,
	const char *method,
	const char *version,
	const char *upload_data, size_t *upload_data_size, void **ptr)
{
	CMediaCenter* self = (CMediaCenter*)cls;

	struct MHD_Response *response;
	int ret = MHD_NO;
	xmlNodePtr node;
	xmlDocPtr doc;
	xmlChar *xmlbuff;
	int buffersize;

	if(0 == strcmp(gMethodGet, method))
	{
		doc = xmlNewDoc(BAD_CAST gXMLVersion );
		node = xmlNewNode(NULL, BAD_CAST gLabelConf);
		xmlDocSetRootElement(doc, node);
		int val = self->onHttpGetMethon(url, node);
		xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
		if(0 == val)
		{
//			SCT_LOGD("GetRep:%s", xmlbuff);
			response = MHD_create_response_from_buffer (buffersize,
					(void *) xmlbuff,
					MHD_RESPMEM_MUST_COPY);
			ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
			MHD_destroy_response (response);
		}
		xmlFree(xmlbuff);
		xmlFreeDoc(doc);

		return ret;
	}
	else if(0 == strcmp(gMethodPost, method))
	{
		CUploadContext *uc = (CUploadContext *)*ptr;
		if (NULL == uc)
		{
			uc = new CUploadContext;
			if(NULL == uc) return MHD_NO; /* out of memory, close connection */
			uc->len = 0;
			uc->max = 64*1000;
			uc->data= new uint8_t[uc->max];
			if(NULL == uc->data)
			{
				delete uc;
				return MHD_NO;
			}
			*ptr = uc;
			return MHD_YES;
		}
		if (0 != *upload_data_size)
		{
			if(uc->max - uc->len < *upload_data_size)
			{
				///copy data to new, free old
				uc->max = 2*uc->max;
				uint8_t * p = new uint8_t[uc->max];
				if(NULL == p)
				{
					delete[] uc->data;
					delete[] uc;
					return MHD_NO;
				}
				memcpy(p, uc->data, uc->len);
				delete[]uc->data;
				uc->data = p;
			}
			memcpy(uc->data+uc->len, upload_data, *upload_data_size);
			uc->len += *upload_data_size;
			*upload_data_size = 0;
			return MHD_YES;
		}

		uc->data[uc->len] = '\0';
//		SCT_LOGD("\n%s", uc->data);
		doc = xmlReadMemory((const char*)uc->data, uc->len, "noname.xml", NULL, 0);
		delete[] uc->data;
		delete[] uc;
		if(NULL == doc) return MHD_NO;

		int val = self->onHttpPostMethon(url, doc);
		xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
		if(0 == val)
		{
			response = MHD_create_response_from_buffer(buffersize, xmlbuff, MHD_RESPMEM_MUST_COPY);
			ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
			MHD_destroy_response (response);

//			SCT_LOGD("rep:%s", xmlbuff);
		}
		xmlFree(xmlbuff);
		xmlFreeDoc(doc);

		return ret;
	}
	return ret;
}
}
